package com.swa99ylum.pxf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.swa99ylum.pxf.cell.CellFiller;
import com.swa99ylum.pxf.cell.indexer.CellIndexer;
import com.swa99ylum.pxf.cell.indexer.FixedCellIndexer;

public class Test1 {

	
	public static void main(String[] args) throws Exception {
		
		
		
		File file = new File("test1.xlsx");
		System.out.println(file.getAbsolutePath());
		
		
		FileInputStream fis = new FileInputStream(file);
		XSSFWorkbook xwb = new XSSFWorkbook(fis);
		
		
		XSSFSheet sheet = xwb.getSheetAt(0);
		XSSFRow row = sheet.createRow(4);
		
		/** ===================================================== */
		
		/** 开发者 需要定义的 数据 */
		
		Student student = new Student(667123 , "张三", "上海", new Date(), "第一批");
		
		CellFiller cellFiller = new CellFiller(0, new Object[]{"batch", "@{id}", "@{name}", "@{address}", "@{birthDay}"});
		
		
		/** ===================================================== */
		
		/** 模拟了 CellFiller 的 fill() 方法 */
		
		List<XSSFCell> cellList = new ArrayList<>();	//待 填值
		List<Object> cellValueList = new ArrayList<>();	//待 填值
		
		Object[] properties = cellFiller.getProperties(); //规定了 宽度，是下面 循环的 标准
		CellIndexer cellIndexer = cellFiller.getCellIndexer();
		
		/*
		 * 设置 cellFiller 的 cells、cellValues
		 */
		for (Object property : properties) {
			
			//1、设置 cellValueList
			Object cellValue = getCellValue(student, property);
			cellValueList.add(cellValue);
			
			
			//2、设置 cellList
			int cellIndex = cellIndexer.getIndexValue();
			
			XSSFCell cell = row.getCell(cellIndex);
			if(cell == null) cell = row.createCell(cellIndex);/** 如果有 "null 单元格"，则将他 补为 "blank 单元格" */
			cellList.add(cell);
			
			cellIndexer.incrementIndexValue();
			
		}
		
		XSSFCell[] cells = (XSSFCell[]) cellList.toArray(new XSSFCell[0]);
		Object[] cellValues = (Object[]) cellValueList.toArray(new Object[0]);
		
		cellFiller.setCells(cells);
		cellFiller.setCellValues(cellValues);
		
		cellFiller.fill();
		
		/** ===================================================== */
		
		FileOutputStream fo = new FileOutputStream(file);
		xwb.write(fo);
		fo.close();
		
		
	}
	
	
	
	private static Object getCellValue(Object data, Object property) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		Object cellValue;
		
		if(property instanceof String) {
			Pattern pattern1 = Pattern.compile("@\\{([\\s\\S]*?)\\}"); //匹配 @{...}
			Matcher matcher1 = pattern1.matcher((String) property);
			
			if (matcher1.matches()) {//javaBean 的 属性
				
				Matcher matcher2 = pattern1.matcher(matcher1.group(1));
				
				if (matcher2.matches()) { //@{@{name}}、@{@{@{name}}}
					 /**
					  * 有多层 @{...}，例如：@{@{name}}
					  * 处理方式：转义一次，将 纯文本 "@{@{name}}" 转为 纯文本"@{name}"
					  */
					cellValue = matcher1.group(1);
					
				}else { //@{name}
					 /**
					  * 只有一层 @{...}，例如：@{name}
					  * 处理方式：取 student 对象的 name 属性，作为返回值
					  */
					
//					System.out.println("==> 匹配成功");//@{name}, @{age}
//					
//					System.out.println(0 + "::\"" + matcher1.group(0) + "\"");
//					System.out.println(1 + "::\"" + matcher1.group(1) + "\"");
//					System.out.println(2 + "::\"" + matcher1.group(2) + "\"");
					
					String propertyName = matcher1.group(1);
					cellValue = PropertyUtils.getProperty(data, propertyName);
					/**
					 * 当 Student 没有 aaa 属性时，PropertyUtils.getProperty() 会报错：
					 * Exception in thread "main" java.lang.NoSuchMethodException: Unknown property 'aaa' on class 'Student'
					 * 
					 * 因为 这个 操作 具有 "开发者的 主观性"，所以不应当 try-catch 这个错误
					 */
				}
				
				
			}else {//纯文本
//				System.out.println("==> 匹配失败");
				
				cellValue = property;
			}
			
		}else {//纯文本
			cellValue = property;
		}
		
		return cellValue;
	}
}
